home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1992 June: ROMin Holiday / ADC Developer CD (1992-06) (''ROMin Holiday'')_iso / Developer Connection - 06-1992.iso / Development Platforms / Apple II / Essentials / Technical.Notes / IIGS / TN.IIGS.022 < prev    next >
Encoding:
Text File  |  1990-09-21  |  6.1 KB  |  145 lines  |  [TEXT/pdos]

  1. Apple II
  2. Technical Notes
  3. _____________________________________________________________________________
  4.                                                   Developer Technical Support
  5.  
  6. Apple IIgs
  7. #22:    Proper Use of Dynamic Segments
  8.  
  9. Rewritten by:    Eric Soldan & Andy Stadler                    September 1990
  10. Written by:      Guillermo Ortiz                                 October 1987
  11.  
  12. This Technical Note discusses strategies that applications can use to deal 
  13. with dynamic segments.
  14. Changes since November 1988:  Rewrote from scratch to address current 
  15. problems.
  16. _____________________________________________________________________________
  17.  
  18. When reading the documentation on dynamic segments, it initially appears that 
  19. they are even better than sliced bread.  While they are incredibly useful, 
  20. there are two issues that make dealing with them somewhat tricky.  The first 
  21. involves loading a dynamic segment; the second involves unloading a dynamic 
  22. segment.  Everything else works fine.
  23.  
  24.  
  25. Loading Dynamic Segments
  26.  
  27. Loading dynamic segments is supposed to happen automatically.  You are 
  28. supposed to be able to call the code in the dynamic segment, and the system 
  29. automatically loads it.  As long as there is enough RAM to load the segment, 
  30. this is exactly what happens.
  31.  
  32. The problem arises when there isn't enough memory.  Immediately you have a 
  33. number of questions, such as "How do I know if it didn't load?" and "How is 
  34. the not-enough-memory error returned?"  Unfortunately, neither of these 
  35. questions is applicable.  Instead, you get a Fatal System Error, which is not 
  36. the most useful thing that could happen.
  37.  
  38. However, there are some reasons for this error.  For example, in the Pascal or 
  39. Toolbox stack frame system, the called function is responsible for removing 
  40. the parameters pushed onto the stack.  If the dynamic segment did not load, 
  41. these parameters cannot be pulled from the stack, and if they are not pulled 
  42. from the stack, the operating system cannot return to the caller.
  43.  
  44. Due to this problem, the best thing to do is to try to load the dynamic 
  45. segment with LoadSegName.  If it loads, then there is (obviously) enough RAM 
  46. for it.  If it does not load, then there was not enough RAM; it's that simple.  
  47. So, to call a function named dynFN in a dynamic segment called dynSeg, you 
  48. would do the following:
  49.  
  50.        LoadSegName("\pDynSeg");
  51.        if (!_toolErr) {
  52.            dynFN(some, number, of, parameters);
  53.            UnLoadSeg(dynFN);
  54.        }
  55.        else ErrorAlert("\pOut of RAM.");
  56.  
  57.  
  58. Unloading Dynamic Segments
  59.  
  60. UnLoadSeg used to have a problem, so the above technique would not have 
  61. worked.  As of System Software 5.0.3, this problem has been fixed.  In the 
  62. example, the code UnLoadSeg(dynFN) does not pass the address of the dynFN that 
  63. was loaded into RAM.  Instead, that address represents the entry in the 
  64. dynamic segment jump table for that particular function.  The jump table is 
  65. always in RAM.  So, you are not actually passing an address of the segment to 
  66. be unloaded, but an address in the jump table.
  67.  
  68. The loader is responsible for figuring out that the address is actually an 
  69. address in the jump table, and it is supposed to unload the segment to which 
  70. the jump table entry refers.  The loader did not handle this case properly 
  71. until 5.0.3.  So, for system disks prior to System Disk 5.0.3, you can 
  72. preserve the segment number returned by the LoadSegName call to issue an 
  73. UnLoadSegNum call to dispose of the dynamic segment.  Due to UnLoadSeg not 
  74. doing the job prior to 5.0.3, you could use UnLoadSegNum.  This also has 
  75. problems.  ExpressLoad changes the segment numbers, so it is difficult to 
  76. maintain the segment numbers if you change the link script.  For these 
  77. reasons, the below technique should be used for system disks prior to 5.0.3:
  78.  
  79. void   sample()
  80. {
  81.        struct    LoadSegNameOut    dynSegInfo;
  82.  
  83.        dynSegInfo = LoadSegName("\pDynSeg");
  84.        if (!_toolErr) {
  85.            dynFN(some, number, of, parameters);
  86.            UnLoadSegNum(dynSegInfo.segNum);
  87.        }
  88.        else ErrorAlert("\pOut of RAM.");
  89. }
  90.  
  91.  
  92. Dynamic Segment Interdependencies:  Just Say No
  93.  
  94. Dynamic Segments calling each other almost always lead to unloading conflicts, 
  95. and more importantly, they defeat the purpose (if they both have to be in 
  96. simultaneously then they might as well be static).  Figure 1 is a sample 
  97. program layout you may want to consider when designing your application 
  98. dynamic segment usage:
  99.  
  100.             Main Program
  101.     Dispatcher & User Interface  <-- static
  102.  
  103.          /       |       \
  104.         /        |        \
  105.  
  106.      Mode 1    Mode 2    Mode 3  <-- dynamic
  107.       Code      Code      Code
  108.  
  109.         \        |        /
  110.          \       |       /
  111.  
  112.         Shared Utility Code      <-- static
  113.  
  114.     Figure 1-Sample Program Layout
  115.  
  116. Also, if one of the dynamic segments described is much more than, say, 32K or 
  117. 40K, you may wish to load a pair (or more) of dynamic segments.  These dynamic 
  118. segment pairs would always be loaded and unloaded simultaneously.  Why?  
  119. Because loading two 25K segments is more likely to succeed than loading one 
  120. 50K segment.
  121.  
  122.  
  123. A Final Warning:
  124.  
  125. Data in a dynamic segment is a tricky issue.  When you call a dynamic segment, 
  126. you are not sure if it got loaded, or if it was already in RAM, and therefore 
  127. you cannot be sure of the values in your global data.  For example, say that 
  128. you have a global variable that represents the number of times that you call 
  129. the dynamic segment.  Every time you call the segment, you would increment 
  130. this variable.  This technique works great until the dynamic segment gets 
  131. purged.  Once it is purged, the next time you call it, the variable area would 
  132. be loaded from disk again, with its original initial value.  The count is no 
  133. longer valid.  To fix this, you can place the global could variable in the 
  134. static globals space for the main code.  Then the variable would not get 
  135. purged, and your count would be valid.  Of course, if you have global data 
  136. that does not ever change, then it is okay for the data to be in the global 
  137. segment.
  138.  
  139.  
  140. Further Reference
  141. _____________________________________________________________________________
  142.   o  GS/OS Reference
  143.   o  Apple IIgs Programmer's Workshop Assembler Reference
  144.  
  145.